Passed
Push — master ( 24613b...a682c9 )
by EMP
04:20
created

main.js ➔ TabState   B

Complexity

Conditions 8

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 5
dl 0
loc 6
rs 7.3333
c 0
b 0
f 0
1
"use strict";
2
3
sodium.ready.then(function() {
4
5
let isReady = true;
6
7
let vaultPage = -4;
8
const vault = new PostVault(function(ok) {
0 ignored issues
show
Bug introduced by
The variable PostVault seems to be never declared. If this is a global, consider adding a /** global: PostVault */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
9
	if (ok) vaultPage = -3;
10
});
11
12
const ae = new AllEars(function(ok) {
13
	if (!ok) {
14
		document.getElementById("greeting").textContent = "Failed loading All-Ears";
15
		return;
16
	}
17
18
	try {
19
		if (localStorage.greeting) {
20
			document.getElementById("greeting").textContent = localStorage.greeting;
21
			document.getElementById("txt_pg").value = localStorage.greeting;
22
		} else localStorage.greeting = document.getElementById("greeting").textContent;
23
	} catch(e) {
24
		document.getElementById("btn_pg").disabled = true;
25
		document.getElementById("txt_pg").disabled = true;
26
		document.getElementById("txt_pg").className = "ita";
27
		document.getElementById("txt_pg").value = "LocalStorage inaccessible";
28
	}
29
30
	document.getElementById("txt_umk").maxLength = "60";
31
});
32
33
function TabState(cur, max, btnDele, btnUpdt) {
34
	this.cur = cur;
35
	this.max = max;
36
	this.btnDele = btnDele;
37
	this.btnUpdt = btnUpdt;
38
}
39
40
const tabs = [
41
	new TabState(0, 0, false, true), // Inbox
42
	new TabState(0, 0, false, false), // Outbx
43
	new TabState(0, 1, true,  false), // Write
44
	new TabState(0, 2, false, false), // Notes
45
	new TabState(0, 2, false, false) // Tools
46
];
47
48
function MsgInfo(msgId, msgType, msgNum) {
49
	this.id = msgId;
50
	this.type = msgType;
51
	this.num = msgNum;
52
}
53
54
let msgDisplay = new MsgInfo(null, null, null);
55
let showHeaders = false;
56
let rowsPerPage = 0;
57
58
let tab = 0;
59
const TAB_INBOX = 0;
60
const TAB_DRBOX = 1;
61
const TAB_WRITE = 2;
62
const TAB_NOTES = 3;
63
const TAB_TOOLS = 4;
64
65
function errorDialog(err, focusAfter) {
66
	if (typeof(err) !== "number" || err < 1) return;
67
68
	let btnDisable = [];
69
	const buttons = document.querySelectorAll("nav > button");
70
	buttons.forEach(function(btn) {
71
		btnDisable.push(btn.disabled);
72
		btn.disabled = true;
73
	});
74
75
	const errMsg = ae.getErrorMessage(err);
76
77
	const dlg = document.querySelector("dialog");
78
	dlg.children[0].style.height = getComputedStyle(document.querySelector("#main1 > div[class='mid']")).height;
79
	dlg.querySelector("h1").textContent = "ERROR " + ((err >= 400) ? err : ("0x" + err.toString(16).padStart(2, "0").toUpperCase()));
80
	dlg.querySelector("p").textContent = (typeof(errMsg) === "string") ? errMsg : errMsg[1];
81
	dlg.show();
82
83
	document.querySelector("dialog > div").onclick = function() {
84
		buttons.forEach(function(btn, i) {btn.disabled = btnDisable[i];});
85
		dlg.close();
86
		if (focusAfter) focusAfter.focus();
87
	};
88
89
	document.onkeyup = function(event) {
90
		document.onkeyup = null;
91
		event.preventDefault();
92
93
		buttons.forEach(function(btn, i) {btn.disabled = btnDisable[i];});
94
		dlg.close();
95
		if (focusAfter) focusAfter.focus();
96
	};
97
}
98
99
function getCountryFlag(countryCode) {
100
	return (!countryCode || countryCode.length !== 2 || countryCode === "??") ? "❔" : sodium.to_string(new Uint8Array([
101
		240, 159, 135, 166 + countryCode.codePointAt(0) - 65,
102
		240, 159, 135, 166 + countryCode.codePointAt(1) - 65
103
	]));
104
}
105
106
function getClockIcon(d) {
107
	const h24 = d.getUTCHours();
108
	let h12 = (h24 === 0 ? 12 : ((h24 > 12) ? h24 - 12 : h24));
109
110
	const m60 = (d.getUTCMinutes() * 60) + d.getUTCSeconds();
111
	let m30 = 0;
112
	if (m60 <= 900) { // <= 15: round down to this hour
113
		m30 = 0;
114
	} else if (m60 > 900 && m60 < 2700) { // 15..45: round to half-past this hour
115
		m30 = 12;
116
	} else { // >= 45: round up to next hour
117
		h12++;
118
		m30 = 0;
119
	}
120
121
	return String.fromCodePoint((128335 + h12) + m30);
122
}
123
124
function clearDisplay() {
125
	document.getElementById("btn_mnext").disabled = true;
126
	document.getElementById("btn_mprev").disabled = true;
127
	document.getElementById("readmsg_export").hidden = true;
128
129
	const el = document.querySelector("#readmsg_main > img, #readmsg_main > audio, #readmsg_main > video, #readmsg_main > embed, #readmsg_main > iframe");
130
	if (!el) return;
131
	if (el.src) URL.revokeObjectURL(el.src);
132
	el.remove();
133
}
134
135
/*
136
function addMsgFlag(abbr, abbrTitle) {
137
	const parent = document.getElementById("readmsg_flags").children[0];
138
139
	const el = document.createElement("abbr");
140
	el.title = abbrTitle;
141
	el.textContent = abbr;
142
143
	parent.appendChild(document.createTextNode(" "));
144
	parent.appendChild(el);
145
}
146
*/
147
148
function displayFile(isHistory, num, showNext) {
149
	if (num < 0 || num >= ae.getUplMsgCount()) return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
150
151
	const fileType = ae.getUplMsgType(num);
152
	if (!fileType) {
153
		if (isHistory) return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
154
		if (showNext === true) return displayFile(false, num + 1, true);
155
		if (showNext === false) return displayFile(false, num - 1, false);
156
		ae.downloadUplMsg(num); return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
157
	}
158
159
	clearDisplay();
160
	document.querySelector("article").scroll(0, 0);
161
	document.querySelector("article").setAttribute("data-msgid", ae.getUplMsgId(num));
162
163
	document.getElementById("btn_mdele").disabled = false;
164
	document.getElementById("btn_msave").disabled = false;
165
	document.getElementById("btn_reply").disabled = true;
166
167
	document.getElementById("btn_msave").onclick = function() {ae.downloadUplMsg(num);};
168
169
	document.getElementById("readmsg_info").hidden = true;
170
	document.getElementById("readmsg_dkim").hidden = true;
171
	document.querySelector("#readmsg_main > h1").textContent = ae.getUplMsgTitle(num);
172
173
	msgDisplay = new MsgInfo(ae.getUplMsgId(num), "upl", num);
174
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
175
176
	document.getElementById("main2").hidden = false;
177
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
178
179
	document.getElementById("btn_mnext").disabled = (num === ae.getUplMsgCount() - 1);
180
	document.getElementById("btn_mprev").disabled = (num === 0);
181
	document.getElementById("btn_mnext").onclick = function() {displayFile(false, num + 1, true);};
182
	document.getElementById("btn_mprev").onclick = function() {displayFile(false, num - 1, false);};
183
184
	if (fileType === "text") {
185
		document.querySelector("#readmsg_main > pre").hidden = false;
186
		try {
187
			document.querySelector("#readmsg_main > pre").textContent = sodium.to_string(ae.getUplMsgBody(num));
188
		} catch(e) {
189
			document.querySelector("#readmsg_main > pre").textContent = "Failed decoding body: " + e.message;
190
		}
191
		return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
192
	}
193
194
	document.querySelector("#readmsg_main > pre").hidden = true;
195
	let el;
196
197
	switch (fileType) {
198
		case "image": {
199
			el = document.createElement("img");
200
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer]));
201
			el.onclick = function() {
202
				if (!document.fullscreen)
203
					this.requestFullscreen();
204
				else
205
					document.exitFullscreen();
206
			};
207
		break;}
208
209
		case "audio":
210
		case "video": {
211
			el = document.createElement(fileType);
212
			el.controls = "controls";
213
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer]));
214
		break;}
215
216
		case "pdf": {
217
			el = document.createElement("embed");
218
			el.type = "application/pdf";
219
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer], {type: "application/pdf"}));
220
		break;}
221
222
		case "html": {
223
			el = document.createElement("iframe");
224
			el.allow = "vertical-scroll";
225
			el.sandbox = "";
226
			el.referrerPolicy = "no-referrer";
227
228
			try {
229
				const sanBody = document.createElement("body");
230
				sanBody.setHTML(sodium.to_string(ae.getUplMsgBody(num).buffer), {sanitizer: new Sanitizer({
0 ignored issues
show
Bug introduced by
The variable Sanitizer seems to be never declared. If this is a global, consider adding a /** global: Sanitizer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
231
					"allowElements": [
232
						"a","div","p",
233
						"h1","h2","h3","h4","h5","h6",
234
						"em","strong","b","i","u"
235
					],
236
					"allowAttributes": {
237
						"href": ["*"]
238
					}
239
				})});
240
241
				el.srcdoc =
242
				"<!doctype html><html>" +
243
					"<head>" +
244
						"<style>" +
245
							"html, body {background: #080a08; color: #fff; scrollbar-color: #222 #333;}\n" +
246
							"body {opacity:0.55;}\n" +
247
							"body > *:first-child {margin-top: 0; padding-top: 0;}\n" +
248
							"a {color: #fff;}\n" +
249
							"button, input, select, textarea {background: #000; color: #fff;}\n" +
250
						"</style>" +
251
					"</head>" +
252
					sanBody.outerHTML +
253
				"</html>";
254
			} catch(e) {
255
				el.srcdoc = "<!doctype html><html><head><style>body {background: #080a08; color: #fff; opacity:0.55;} h1 {margin: 0;}</style><body><h1>Error</h1><p>" + e.message + "</p></body></html>";
256
			}
257
		break;}
258
259
		case "svg": {
260
			el = document.createElement("iframe");
261
			el.allow = "";
262
			el.sandbox = "";
263
			el.referrerPolicy = "no-referrer";
264
			el.srcdoc = "<!doctype><html><head><style>body,html,svg {margin: 0; padding: 0; border: 0; height: 100%; width: 100%; display: block; background: #080a08;}</style></head><body>" + sodium.to_string(ae.getUplMsgBody(num).buffer) + "</body></html>";
265
		break;}
266
267
		default: return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
268
	}
269
270
	document.getElementById("readmsg_main").appendChild(el);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
271
}
272
273
function displayMsg(isHistory, isInt, num) {
274
	clearDisplay();
275
	document.getElementById("btn_mdele").disabled = false;
276
277
	document.querySelector("article").scroll(0, 0);
278
	document.querySelector("article").setAttribute("data-msgid", isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num));
279
280
	document.getElementById("btn_msave").disabled = false;
281
	document.getElementById("btn_msave").onclick = function() {displayExport(false, isInt, num);};
282
283
	const ts = isInt? ae.getIntMsgTime(num) : ae.getExtMsgTime(num);
284
285
	if (!isInt || (ae.getIntMsgFrom(num) !== "public" && ae.getIntMsgFrom(num) !== "system")) {
286
		document.getElementById("btn_reply").disabled = false;
287
288
		document.getElementById("btn_reply").onclick = function() {
289
			document.getElementById("write_recv").value = isInt? ae.getIntMsgFrom(num) : ae.getExtMsgReplyAddress(num);
290
			document.getElementById("write_subj").value = isInt? ae.getIntMsgTitle(num) : ae.getExtMsgTitle(num);
291
			if (!document.getElementById("write_subj").value.startsWith("Re:")) document.getElementById("write_subj").value = "Re: " + document.getElementById("write_subj").value;
292
			document.querySelector("#write2_pkey > input").value = isInt? ae.getIntMsgApk(num) : "";
293
294
			document.getElementById("write_recv").readOnly = !isInt;
295
			document.getElementById("write_subj").readOnly = !isInt;
296
			document.getElementById("write_subj").setAttribute("data-replyid", isInt? "" : ae.getExtMsgHdrId(num));
297
298
			tabs[TAB_WRITE].cur = 0;
299
			document.getElementById("btn_write").disabled = false;
300
			document.getElementById("btn_write").click();
301
			document.getElementById("write_body").focus();
302
303
			for (const opt of document.getElementById("write_from").options) {
304
				if (opt.value === (isInt ? ae.getIntMsgTo(num) : ae.getExtMsgEnvTo(num).split("@")[0].toLowerCase())) {
305
					opt.selected = true;
306
				}
307
			}
308
		};
309
	} else {
310
		document.getElementById("btn_reply").disabled = true;
311
	}
312
313
	document.getElementById("readmsg_info").hidden = false;
314
	document.querySelector("#readmsg_main > pre").hidden = false;
315
316
	document.getElementById("readmsg_envto").textContent = isInt ? "" : ae.getExtMsgEnvTo(num);
317
	document.getElementById("readmsg_hdrto").textContent = isInt ? ae.getIntMsgTo(num) : (ae.getExtMsgHdrTo(num));
318
	if(!isInt && ae.getExtMsgDnTo(num)) {
319
		const span = document.createElement("span");
320
		span.className = "sans";
321
		span.textContent = " • " + ae.getExtMsgDnTo(num);
322
		document.getElementById("readmsg_hdrto").appendChild(span);
323
	}
324
325
	const tzOs = new Date().getTimezoneOffset();
326
	const msgDate = new Date((ts * 1000) + (tzOs * -60000));
327
	document.getElementById("readmsg_date").children[0].textContent = getClockIcon(msgDate);
328
	document.getElementById("readmsg_date").children[1].dateTime = new Date(ts * 1000).toISOString();
329
330
	if (isInt) {
331
		document.getElementById("readmsg_dkim").hidden = true;
332
333
		document.querySelector("#readmsg_main > h1").textContent = ae.getIntMsgTitle(num);
334
		document.querySelector("#readmsg_main > pre").textContent = ae.getIntMsgBody(num);
335
336
		document.getElementById("readmsg_date").children[1].textContent = msgDate.toISOString().slice(0, 19).replace("T", " ");
337
338
		document.getElementById("readmsg_ip").style.visibility = "hidden";
339
		document.getElementById("readmsg_rdns").style.visibility = "hidden";
340
		document.getElementById("readmsg_greet").style.visibility = "hidden";
341
		document.getElementById("readmsg_cert").style.visibility = "hidden";
342
		document.getElementById("readmsg_envfrom").style.visibility = "hidden";
343
		document.getElementById("readmsg_envto").style.visibility = "hidden";
344
345
		if (ae.getIntMsgFrom(num) !== "system" && ae.getIntMsgFrom(num) !== "public") {
346
			document.getElementById("readmsg_tls").style.visibility = "visible";
347
			document.getElementById("readmsg_tls").children[0].textContent = ae.getIntMsgApk(num);
348
		} else document.getElementById("readmsg_tls").style.visibility = "hidden";
349
350
		let symbol = document.createElement("span");
351
		if      (ae.getIntMsgLevel(num) === 3 && ae.getIntMsgFrom(num) === "system") {symbol.title = "System message"; symbol.textContent = "🅢";}
352
		else if (ae.getIntMsgLevel(num) === 3 && ae.getIntMsgFrom(num) === "public") {symbol.title = "Public announcement"; symbol.textContent = "🅟";}
353
		else if (ae.getIntMsgLevel(num) === 3) {symbol.title = "Administrator"; symbol.textContent = "🅐";}
354
		else if (ae.getIntMsgLevel(num) === 2) {symbol.title = "Level 2";  symbol.textContent = "➋";}
355
		else if (ae.getIntMsgLevel(num) === 1) {symbol.title = "Level 1";  symbol.textContent = "➊";}
356
		else if (ae.getIntMsgLevel(num) === 0) {symbol.title = "Level 0";  symbol.textContent = "🄌";}
357
		else {symbol.title = "Invalid level"; symbol.textContent = "⚠";}
358
359
		document.getElementById("readmsg_hdrfrom").replaceChildren(symbol, document.createTextNode(" " + ae.getIntMsgFrom(num)));
360
361
//		if ( ae.getIntMsgFlagE2ee(num)) addMsgFlag("E2EE", "End-to-end encrypted");
362
	} else {
363
		const headers = document.createElement("p");
364
		headers.textContent = ae.getExtMsgHeaders(num);
365
		headers.className = "mono";
366
		headers.hidden = !showHeaders;
367
368
		const body = document.createElement("p");
369
		body.innerHTML = ae.getExtMsgBody(num, false);
370
371
		document.querySelector("#readmsg_main > pre").replaceChildren(headers, body);
372
373
		const h1 = document.querySelector("#readmsg_main > h1");
374
		h1.textContent = ae.getExtMsgTitle(num);
375
		h1.style.cursor = headers.textContent? "pointer" : "";
376
		h1.onclick = function() {
377
			if (!headers.textContent) return;
378
			showHeaders = !showHeaders;
379
			headers.hidden = !showHeaders;
380
		};
381
382
		let hdrSecs = Math.abs(ae.getExtMsgHdrTime(num));
383
		let hdrTime = "";
384
		if (hdrSecs >= 3600) {
385
			const hdrHours = Math.floor(hdrSecs / 3600);
386
			hdrTime += hdrHours.toString() + "h ";
387
			hdrSecs -= hdrHours * 3600;
388
		}
389
		if (hdrSecs >= 60) {
390
			const hdrMins = Math.floor(hdrSecs / 60);
391
			hdrTime += hdrMins.toString() + "m ";
392
			hdrSecs -= hdrMins * 60;
393
		}
394
		hdrTime += hdrSecs + "s";
395
396
		const hdrTz = (ae.getExtMsgHdrTz(num) >= 0 ? "+" : "-") + Math.floor(Math.abs(ae.getExtMsgHdrTz(num)) / 60).toString().padStart(2, "0") + (Math.abs(ae.getExtMsgHdrTz(num)) % 60).toString().padStart(2, "0");
397
398
		let spans = [document.createElement("span"), document.createElement("span"), document.createElement("span")];
399
		spans[0].textContent = msgDate.toISOString().slice(0, 19).replace("T", " ");
400
		spans[1].className = "sans";
401
		spans[1].textContent = " • ";
402
		spans[2].textContent = hdrTz + " " + ((ae.getExtMsgHdrTime(num) >= 0) ? "+" : "-") + hdrTime;
403
		document.getElementById("readmsg_date").children[1].replaceChildren(...spans);
404
405
		document.getElementById("readmsg_ip").style.visibility = "visible";
406
		document.getElementById("readmsg_rdns").style.visibility = "visible";
407
		document.getElementById("readmsg_greet").style.visibility = "visible";
408
		document.getElementById("readmsg_tls").style.visibility = "visible";
409
		document.getElementById("readmsg_cert").style.visibility = "visible";
410
		document.getElementById("readmsg_envfrom").style.visibility = "visible";
411
		document.getElementById("readmsg_envto").style.visibility = "visible";
412
413
		// DKIM
414
		if (ae.getExtMsgDkimCount(num) > 0) {
415
			document.getElementById("readmsg_dkim").hidden = false;
416
417
			document.querySelectorAll("#readmsg_dkim div").forEach(function(d, i) {
418
				if (i >= ae.getExtMsgDkimCount(num)) {
419
					d.textContent = "";
420
					return;
421
				}
422
				d.textContent = (ae.getExtMsgDkimValidSig(num, i) ? "OK" : "❌") + " " + ae.getExtMsgDkimAlgo(num, i) + " " + ae.getExtMsgDkimHeadHash(num, i) + "/" + ae.getExtMsgDkimBodyHash(num, i) + ": "
423
					+ (ae.getExtMsgDkimIdentity(num, i) ? (ae.getExtMsgDkimIdentity(num, i) + "|") : "") + ae.getExtMsgDkimDomain(num, i) + "|" + ae.getExtMsgDkimSelector(num, i)
424
					+ ((ae.getExtMsgDkimTs(num, i) > 0) ? (" @" + ae.getExtMsgDkimTs(num, i)) : "");
425
			});
426
		} else {
427
			document.getElementById("readmsg_dkim").hidden = true;
428
		}
429
430
		// Left side
431
		document.getElementById("readmsg_country").textContent = getCountryFlag(ae.getExtMsgCcode(num));
432
		document.getElementById("readmsg_country").title = ae.getExtMsgCname(num);
433
		document.getElementById("readmsg_ip").children[1].textContent = ae.getExtMsgIp(num) + (ae.getExtMsgFlagIpBl(num) ? " ❗" : "");
434
		document.getElementById("readmsg_ip").children[2].textContent = " • " + ae.getExtMsgAuSys(num);
435
		document.getElementById("readmsg_tls").children[0].textContent = ae.getExtMsgTLS(num);
436
437
		// Right side
438
		document.getElementById("readmsg_greet").children[0].textContent = ae.getExtMsgGreet(num) + (ae.getExtMsgFlagGrDm(num) ? " ✓" : "");
439
		document.getElementById("readmsg_rdns").children[0].textContent = ae.getExtMsgRdns(num) + (ae.getExtMsgGreet(num).toLowerCase() === ae.getExtMsgRdns(num).toLowerCase() ? " ✓" : "");
440
		document.getElementById("readmsg_cert").children[0].textContent = ae.getExtMsgTlsDomain(num) ? (ae.getExtMsgTlsDomain(num) + " ✓") : "";
441
		document.getElementById("readmsg_envfrom").textContent = ae.getExtMsgEnvFrom(num);
442
		document.getElementById("readmsg_hdrfrom").textContent = ae.getExtMsgHdrFrom(num);
443
		if (ae.getExtMsgDnFrom(num)) {
444
			const span = document.createElement("span");
445
			span.className = "sans";
446
			span.textContent = " • " + ae.getExtMsgDnFrom(num);
447
			document.getElementById("readmsg_hdrfrom").appendChild(span);
448
		}
449
450
/*
451
		clearMsgFlags();
452
		if (!ae.getExtMsgFlagPExt(num)) addMsgFlag("SMTP", "The sender did not use the Extended (ESMTP) protocol");
453
		if ( ae.getExtMsgFlagRare(num)) addMsgFlag("RARE", "The sender issued unusual command(s)");
454
		if ( ae.getExtMsgFlagFail(num)) addMsgFlag("FAIL", "The sender issued invalid command(s)");
455
		if ( ae.getExtMsgFlagPErr(num)) addMsgFlag("PROT", "The sender violated the protocol");
456
*/
457
	}
458
459
	document.getElementById("readmsg_main").hidden = false;
460
	document.getElementById("main2").hidden = false;
461
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
462
463
	msgDisplay = new MsgInfo(isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num), isInt? "int" : "ext", num);
464
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
465
}
466
467
function displayExport(isHistory, isInt, num) {
468
	clearDisplay();
469
	document.getElementById("readmsg_main").hidden = true;
470
	document.getElementById("readmsg_export").hidden = false;
471
	document.getElementById("btn_msave").blur();
472
	document.getElementById("btn_msave").disabled = true;
473
	document.getElementById("btn_reply").disabled = true;
474
	document.getElementById("btn_mdele").disabled = true;
475
476
//	document.querySelector("#readmsg_export > div:nth-child(1)").onclick = function() {};
477
	document.querySelector("#readmsg_export > div:nth-child(2)").onclick = function() {if (isInt) {ae.downloadIntMsg(num);} else {ae.downloadExtMsg(num);} displayMsg(false, isInt, num);};
478
	document.querySelector("#readmsg_export > div:nth-child(3)").onclick = function() {if (isInt) {ae.htmlIntMsg(num, true);} else {ae.htmlExtMsg(num, true);} displayMsg(false, isInt, num);};
479
	document.querySelector("#readmsg_export > div:nth-child(4)").onclick = function() {if (isInt) {ae.txtIntMsg(num, true);} else {ae.txtExtMsg(num, true);} displayMsg(false, isInt, num);};
480
	document.querySelector("#readmsg_export > div:nth-child(5)").onclick = function() {if (isInt) {ae.printIntMsg(num);} else {ae.printExtMsg(num);} displayMsg(false, isInt, num);};
481
	document.querySelector("#readmsg_export > div:nth-child(6)").onclick = function() {navigator.clipboard.writeText(isInt? ae.txtIntMsg(num, false) : ae.txtExtMsg(num, false)); displayMsg(false, isInt, num);};
482
483
	msgDisplay = new MsgInfo(isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num), isInt? "int_exp" : "ext_exp", num);
484
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
485
}
486
487
function displayOutMsg(isHistory, num) {
488
	clearDisplay();
489
	document.querySelector("article").scroll(0, 0);
490
	document.querySelector("article").setAttribute("data-msgid", ae.getOutMsgId(num));
491
492
	document.getElementById("btn_mdele").disabled = false;
493
	document.getElementById("btn_msave").disabled = true;
494
	document.getElementById("btn_reply").disabled = true;
495
496
	document.getElementById("readmsg_info").hidden = false;
497
	document.querySelector("#readmsg_main > pre").hidden = false;
498
499
	document.querySelector("#readmsg_main > h1").textContent = ae.getOutMsgSubj(num);
500
	document.querySelector("#readmsg_main > pre").textContent = ae.getOutMsgBody(num);
501
502
	document.getElementById("readmsg_hdrto").style.visibility   = "visible";
503
	document.getElementById("readmsg_hdrfrom").style.visibility = "visible";
504
	document.getElementById("readmsg_envto").style.visibility   = "visible";
505
	document.getElementById("readmsg_envfrom").style.visibility = "hidden";
506
507
	document.getElementById("readmsg_hdrfrom").textContent = ae.getOutMsgFrom(num);
508
509
	document.getElementById("readmsg_envto").textContent = ae.getOutMsgMxDom(num);
510
	document.getElementById("readmsg_hdrto").textContent = ae.getOutMsgTo(num);
511
512
	const ts = ae.getOutMsgTime(num);
513
	const tzOs = new Date().getTimezoneOffset();
514
	document.getElementById("readmsg_date").children[1].textContent = new Date((ts * 1000) + (tzOs * -60000)).toISOString().slice(0, 19).replace("T", " ");
515
516
	const isInt = ae.getOutMsgIsInt(num);
517
	document.getElementById("readmsg_ip").style.visibility    = isInt? "hidden" : "visible";
518
	document.getElementById("readmsg_rdns").style.visibility  = /*isInt?*/ "hidden" /*: "visible"*/; // TODO
519
	document.getElementById("readmsg_tls").style.visibility   = /*isInt?*/ "hidden" /*: "visible"*/; // TODO
520
	document.getElementById("readmsg_cert").style.visibility  = /*isInt?*/ "hidden" /*: "visible"*/; // TODO
521
	document.getElementById("readmsg_greet").style.visibility = isInt? "hidden" : "visible";
522
523
	if (!isInt) {
524
		document.getElementById("readmsg_ip").children[1].textContent = ae.getOutMsgIp(num);
525
		document.getElementById("readmsg_country").textContent = getCountryFlag(ae.getOutMsgCcode(num));
526
		document.getElementById("readmsg_country").title = ae.getOutMsgCname(num);
527
//		document.getElementById("readmsg_tls").children[0].textContent = ae.getOutMsgTLS(num);
528
		document.getElementById("readmsg_greet").children[0].textContent = ae.getOutMsgGreet(num);
529
	}
530
531
//	if ( ae.getOutMsgFlagE2ee(num)) addMsgFlag("E2EE", "End-to-end encrypted");
532
533
	document.getElementById("main2").hidden = false;
534
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
535
536
	msgDisplay = new MsgInfo(ae.getOutMsgId(num), "out", num);
537
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
538
}
539
540
function updateAddressButtons() {
541
	const limitReached = (ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31);
542
	document.getElementById("btn_address_create_normal").disabled = (limitReached || ae.getAddressCountNormal() >= ae.getLimitNormalA(ae.getOwnLevel()));
543
	document.getElementById("btn_address_create_shield").disabled = (limitReached || ae.getAddressCountShield() >= ae.getLimitShieldA(ae.getOwnLevel()));
544
}
545
546
function updateAddressCounts() {
547
	document.querySelector("#tbd_accs > tr > td:nth-child(3)").textContent = ae.getAddressCountNormal();
548
	document.querySelector("#tbd_accs > tr > td:nth-child(4)").textContent = ae.getAddressCountShield();
549
550
	document.getElementById("limit_normal").textContent = (ae.getAddressCountNormal() + "/" + ae.getLimitNormalA(ae.getOwnLevel())).padStart(ae.getLimitNormalA(ae.getOwnLevel()) > 9 ? 5 : 1);
551
	document.getElementById("limit_shield").textContent = (ae.getAddressCountShield() + "/" + ae.getLimitShieldA(ae.getOwnLevel())).padStart(ae.getLimitShieldA(ae.getOwnLevel()) > 9 ? 5 : 1);
552
	document.getElementById("limit_total").textContent = ((ae.getAddressCountNormal() + ae.getAddressCountShield()) + "/" + ae.getAddrPerUser()).padStart(5);
553
554
	updateAddressButtons();
555
//	document.getElementById("getapk_result").textContent = ae.getOwnApk(document.getElementById("getapk_addr").value);
556
}
557
558
function addOwnAccount() {
559
	const row = document.getElementById("tbd_accs").insertRow(-1);
560
561
	let cell;
562
	cell = row.insertCell(-1); cell.textContent = ae.uidToName(ae.getOwnUid());
563
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.getTotalMsgBytes() / 1048576); // MiB
564
	cell = row.insertCell(-1); cell.textContent = ae.getAddressCountNormal();
565
	cell = row.insertCell(-1); cell.textContent = ae.getAddressCountShield();
566
567
	cell = row.insertCell(-1);
568
	let btn = document.createElement("button");
569
	btn.type = "button";
570
	btn.textContent = "+";
571
	btn.disabled = true;
572
	cell.appendChild(btn);
573
574
	cell = row.insertCell(-1); cell.textContent = ae.getOwnLevel();
575
576
	cell = row.insertCell(-1);
577
	btn = document.createElement("button");
578
	btn.type = "button";
579
	btn.textContent = "−";
580
	btn.disabled = true;
581
	btn.id = "btn_lowme";
582
	btn.onclick = function() {
583
		const newLevel = parseInt(row.cells[5].textContent, 10) - 1;
584
		ae.Account_Update(ae.getOwnUid(), newLevel, function(error) {
585
			if (error === 0) {
586
				row.cells[5].textContent = newLevel;
587
				if (newLevel === 0) {document.getElementById("btn_lowme").disabled = true;}
588
			} else errorDialog(error);
589
		});
590
	};
591
	cell.appendChild(btn);
592
593
	cell = row.insertCell(-1);
594
	btn = document.createElement("button");
595
	btn.type = "button";
596
	btn.textContent = "X";
597
	btn.disabled = true;
598
	btn.id = "btn_delme";
599
	btn.onclick = function() {
600
		ae.Account_Delete(ae.getOwnUid(), function(error) {
601
			if (error === 0) {
602
				row.remove();
603
				document.getElementById("fs_users").disabled = true;
604
			} else errorDialog(error);
605
		});
606
	};
607
	cell.appendChild(btn);
608
}
609
610
function adjustLevel(uid, level, c) {
611
	const fs = document.getElementById("tbl_accs");
612
	fs.disabled = true;
613
614
	ae.Account_Update(uid, level, function(error) {
615
		fs.disabled = false;
616
617
		if (error === 0) {
618
			c[4].children[0].disabled = (level === 3);
619
			c[5].textContent = level;
620
			c[6].children[0].disabled = (level === 0);
621
		} else errorDialog(error);
622
	});
623
}
624
625
function addMsg(isInt, i) {
626
	const row = document.getElementById("tbl_inbox").insertRow(-1);
627
	row.setAttribute("data-msgid", isInt? ae.getIntMsgId(i) : ae.getExtMsgId(i));
628
629
	const ts = isInt? ae.getIntMsgTime(i) : ae.getExtMsgTime(i);
630
	const el = document.createElement("time");
631
	el.dateTime = new Date(ts * 1000).toISOString();
632
	el.textContent = new Date((ts * 1000) + (new Date().getTimezoneOffset() * -60000)).toISOString().slice(0, 10);
633
	let cell = row.insertCell(-1);
634
	cell.appendChild(el);
635
636
	cell = row.insertCell(-1);
637
	cell.textContent = isInt? ae.getIntMsgTitle(i) : ae.getExtMsgTitle(i);
638
	if (!cell.textContent) cell.textContent = "(fail)";
639
640
	if (isInt) {
641
		cell = row.insertCell(-1);
642
		cell.textContent = ae.getIntMsgFrom(i);
643
		cell.className = (ae.getIntMsgFrom(i).length === 16) ? "mono" : "";
644
	} else {
645
		let from1 = ae.getExtMsgHdrFrom(i);
646
		if (!from1) from1 = ae.getExtMsgEnvFrom(i);
647
		const from2 = from1.substring(from1.indexOf("@") + 1);
648
		cell = row.insertCell(-1);
649
		cell.textContent = from1.substring(0, from1.indexOf("@"));
650
651
		const flag = document.createElement("abbr");
652
		flag.textContent = getCountryFlag(ae.getExtMsgCcode(i));
653
		flag.title = ae.getExtMsgCname(i);
654
655
		const fromText = document.createElement("span");
656
		fromText.textContent = " " + from2;
657
658
		cell = row.insertCell(-1);
659
		cell.appendChild(flag);
660
		cell.appendChild(fromText);
661
	}
662
663
	row.onclick = function() {
664
		displayMsg(false, isInt, i);
665
	};
666
}
667
668
function setRowsPerPage(tbl) {
669
	tbl.replaceChildren();
670
	const row = tbl.insertRow(-1);
671
	const cell = row.insertCell(-1);
672
	cell.textContent = "0";
673
	rowsPerPage = Math.floor(getComputedStyle(tbl).height.replace("px", "") / getComputedStyle(tbl.getElementsByTagName("tr")[0]).height.replace("px", ""));
674
	tbl.replaceChildren();
675
}
676
677
function showInbox() {
678
	const tbl = document.getElementById("tbl_inbox");
679
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
680
681
	const maxExt = ae.getExtMsgCount();
682
	const maxInt = ae.getIntMsgCount();
683
	const loadMore = ae.getReadyMsgBytes() < ae.getTotalMsgBytes();
684
685
	if (maxExt + maxInt > 0) {
686
		tabs[TAB_INBOX].max = Math.floor((maxExt + maxInt - (loadMore? 0 : 1)) / rowsPerPage);
687
		document.getElementById("btn_rght").disabled = (tabs[TAB_INBOX].cur >= tabs[TAB_INBOX].max);
688
		tbl.replaceChildren();
689
690
		let skipMsgs = rowsPerPage * tabs[TAB_INBOX].cur;
691
		let numExt = 0;
692
		let numInt = 0;
693
		let numAdd = 0;
694
695
		while (numAdd < rowsPerPage) {
696
			const tsInt = (numInt < maxInt) ? ae.getIntMsgTime(numInt) : -1;
697
			const tsExt = (numExt < maxExt) ? ae.getExtMsgTime(numExt) : -1;
698
			if (tsInt === -1 && tsExt === -1) break;
699
700
			if (tsInt !== -1 && (tsExt === -1 || tsInt > tsExt)) {
701
				if (skipMsgs > 0) skipMsgs--; else {addMsg(true, numInt); numAdd++;}
702
				numInt++;
703
			} else if (tsExt !== -1) {
704
				if (skipMsgs > 0) skipMsgs--; else {addMsg(false, numExt); numAdd++;}
705
				numExt++;
706
			}
707
		}
708
	} else {
709
		tabs[TAB_INBOX].max = 0;
710
	}
711
712
	if (loadMore && tabs[TAB_INBOX].cur >= tabs[TAB_INBOX].max) {
713
		const row = tbl.insertRow(-1);
714
		const cell = row.insertCell(-1);
715
		cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
716
717
		row.onclick = function() {
718
			tbl.style.opacity = 0.5;
719
720
			ae.Message_Browse(false, false, function(errorBrowse) {
721
				tbl.style.opacity = 1;
722
723
				if (errorBrowse !== 0) {
724
					errorDialog(errorBrowse);
725
					return;
726
				}
727
728
				showInbox();
729
			});
730
		};
731
	}
732
}
733
734
function showDrbox() {
735
	const tbl = document.getElementById("tbl_drbox");
736
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
737
738
	const drCount = ae.getOutMsgCount();
739
	const loadMore = ae.getReadyMsgBytes() < ae.getTotalMsgBytes();
740
741
	if (drCount > 0) {
742
		tabs[TAB_DRBOX].max = Math.floor((drCount - (loadMore? 0 : 1)) / rowsPerPage);
743
		document.getElementById("btn_rght").disabled = (tabs[TAB_DRBOX].cur >= tabs[TAB_DRBOX].max);
744
		tbl.replaceChildren();
745
746
		let skipMsgs = rowsPerPage * tabs[TAB_DRBOX].cur;
747
		let numAdd = 0;
748
749
		for (let i = 0; numAdd < rowsPerPage && i < drCount; i++) {
750
			if (skipMsgs > 0) {
751
				skipMsgs--;
752
				continue;
753
			}
754
755
			const row = tbl.insertRow(-1);
756
			row.setAttribute("data-msgid", ae.getOutMsgId(i));
757
758
			let cell;
759
			cell = row.insertCell(-1); cell.textContent = new Date(ae.getOutMsgTime(i) * 1000).toISOString().slice(0, 10);
760
			cell = row.insertCell(-1); cell.textContent = ae.getOutMsgSubj(i);
761
			row.onclick = function() {displayOutMsg(false, i);};
762
763
			numAdd++;
764
		}
765
	} else {
766
		tabs[TAB_DRBOX].max = 0;
767
	}
768
769
	if (loadMore && tabs[TAB_DRBOX].cur >= tabs[TAB_DRBOX].max) {
770
		const row = tbl.insertRow(-1);
771
		const cell = row.insertCell(-1);
772
		cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
773
774
		row.onclick = function() {
775
			tbl.style.opacity = 0.5;
776
777
			ae.Message_Browse(false, false, function(errorBrowse) {
778
				tbl.style.opacity = 1;
779
780
				if (errorBrowse !== 0) {
781
					errorDialog(errorBrowse);
782
					return;
783
				}
784
785
				showDrbox();
786
			});
787
		};
788
	}
789
}
790
791
function showFiles() {
792
	const tbl = document.getElementById("tbl_files");
793
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
794
795
	const msgCount = ae.getUplMsgCount() + ((vaultPage >= 0) ? vault.getTotalFiles() : 0);
796
	const loadMore = ae.getReadyMsgBytes() < ae.getTotalMsgBytes();
797
798
	if (msgCount > 0) {
799
		tabs[TAB_NOTES].max = 2 + Math.floor((msgCount - (loadMore? 0 : 1)) / rowsPerPage);
800
		document.getElementById("btn_rght").disabled = (tabs[TAB_NOTES].cur >= tabs[TAB_NOTES].max);
801
		tbl.replaceChildren();
802
803
		let skipMsgs = rowsPerPage * (tabs[TAB_NOTES].cur - 2);
804
		let numAdd = 0;
805
806
		for (let i = 0; numAdd < rowsPerPage && i < ae.getUplMsgCount(); i++) {
807
			if (skipMsgs > 0) {
808
				skipMsgs--;
809
				continue;
810
			}
811
812
			const row = tbl.insertRow(-1);
813
			row.setAttribute("data-msgid", ae.getUplMsgId(i));
814
			row.className = "rowfile";
815
816
			let cell = row.insertCell(-1);
817
			cell.textContent = new Date(ae.getUplMsgTime(i) * 1000).toISOString().slice(0, 10);
818
			cell.onclick = function() {displayFile(false, i, null);};
819
820
			cell = row.insertCell(-1);
821
			cell.textContent = (ae.getUplMsgBytes(i) / 1024).toFixed(0).padStart(4, " ");
822
			cell.onclick = function() {displayFile(false, i, null);};
823
824
			cell = row.insertCell(-1);
825
			const parentNum = ae.getUplMsgParent(i);
826
			if (typeof(parentNum) === "number") {
827
				cell.textContent = ae.getExtMsgTitle(parentNum);
828
				cell.onclick = function() {displayMsg(false, false, parentNum);};
829
			} else if (parentNum === false) {
830
				cell.textContent = "Upload";
831
			} else {
832
				cell.textContent = "Unknown";
833
			}
834
835
			cell = row.insertCell(-1);
836
			cell.textContent = ae.getUplMsgTitle(i);
837
			cell.onclick = function() {displayFile(false, i, null);};
838
839
			cell = row.insertCell(-1);
840
			const btn = document.createElement("button");
841
			btn.setAttribute("data-msgid", ae.getUplMsgId(i));
842
			btn.type = "button";
843
			btn.textContent = "X";
844
			btn.onclick = function() {
845
				ae.Message_Delete(this.getAttribute("data-msgid"), function(error) {
846
					if (error === 0) showFiles();
847
					else errorDialog(error);
848
				});
849
			};
850
			cell.appendChild(btn);
851
852
			numAdd++;
853
		}
854
855
		if (vaultPage >= 0) {
856
			for (let i = 0; numAdd < rowsPerPage && i < 256; i++) {
857
				if (vault.getFileSize(i) < 1) continue;
858
859
				if (skipMsgs > 0) {
860
					skipMsgs--;
861
					continue;
862
				}
863
864
				const row = tbl.insertRow(-1);
865
				row.className = "rowfile";
866
867
				let cell = row.insertCell(-1);
868
				cell.textContent = new Date(vault.getFileTime(i) * 1000).toISOString().slice(0, 10);
869
870
				cell = row.insertCell(-1);
871
				cell.textContent = (vault.getFileSize(i) / 1024).toFixed(0).padStart(4, " ");
872
873
				cell = row.insertCell(-1);
874
				cell.textContent = "Vault";
875
876
				cell = row.insertCell(-1);
877
				cell.textContent = vault.getFilePath(i);
878
				cell.onclick = function() {vault.downloadFile(i, function(m,p){}, function(msg) {
0 ignored issues
show
Unused Code introduced by
The parameter m is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter p is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
879
					if (msg !== "Done") errorDialog(404);
880
				});};
881
882
				cell = row.insertCell(-1);
883
				const btn = document.createElement("button");
884
				btn.type = "button";
885
				btn.textContent = "X";
886
				btn.onclick = function() {
887
					vault.deleteFile(i, function(error) {
888
						if (error === 0) showFiles();
889
						else errorDialog(error);
890
					});
891
				};
892
				cell.appendChild(btn);
893
894
				numAdd++;
895
			}
896
		}
897
	} else tabs[TAB_NOTES].max = 2;
898
899
	if (loadMore && tabs[TAB_NOTES].cur >= tabs[TAB_NOTES].max) {
900
		const row = tbl.insertRow(-1);
901
		row.className = "rowfilex";
902
903
		let cell = row.insertCell(-1);
904
		if (ae.getReadyMsgBytes() < ae.getTotalMsgBytes()) {
905
			cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
906
			cell.onclick = function() {
907
				tbl.style.opacity = 0.5;
908
909
				ae.Message_Browse(false, false, function(errorBrowse) {
910
					tbl.style.opacity = 1;
911
912
					if (errorBrowse !== 0) {
913
						errorDialog(errorBrowse);
914
						return;
915
					}
916
917
					showFiles();
918
				});
919
			};
920
		}
921
922
		cell = row.insertCell(-1);
0 ignored issues
show
Unused Code introduced by
The assignment to variable cell seems to be never used. Consider removing it.
Loading history...
923
	}
924
}
925
926
function addAccountToTable(i) {
927
	if (ae.getOwnUid() === ae.admin_getUserUid(i)) return;
928
929
	const row = document.getElementById("tbd_accs").insertRow(-1);
930
	let cell;
931
	cell = row.insertCell(-1); cell.textContent = ae.uidToName(ae.admin_getUserUid(i));
932
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.admin_getUserKib(i) / 1024);
933
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserNrm(i);
934
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserShd(i);
935
936
	cell = row.insertCell(-1);
937
	let btn = document.createElement("button");
938
	btn.type = "button";
939
	btn.textContent = "+";
940
	btn.disabled = (ae.admin_getUserLvl(i) === 3);
941
	btn.onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(ae.admin_getUserUid(i), ae.admin_getUserLvl(i) + 1, c);};
942
	cell.appendChild(btn);
943
944
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserLvl(i);
945
946
	cell = row.insertCell(-1);
947
	btn = document.createElement("button");
948
	btn.type = "button";
949
	btn.textContent = "−";
950
	btn.disabled = (ae.admin_getUserLvl(i) === 0);
951
	btn.onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(ae.admin_getUserUid(i), ae.admin_getUserLvl(i) - 1, c);};
952
	cell.appendChild(btn);
953
954
	cell = row.insertCell(-1);
955
	btn = document.createElement("button");
956
	btn.type = "button";
957
	btn.textContent = "X";
958
	btn.onclick = function() {
959
		const tr = this.parentElement.parentElement;
960
		ae.Account_Delete(ae.admin_getUserUid(i), function(error) {
961
			if (error === 0) tr.remove(); else errorDialog(error);
962
		});
963
	};
964
	cell.appendChild(btn);
965
}
966
967
function updateLimits() {
968
	const tbl = document.querySelector("#tbl_limits > tbody");
969
970
	if (ae.isUserAdmin()) {
971
		for (let i = 0; i < 4; i++) {
972
			tbl.rows[i].cells[1].children[0].value = ae.getLimitStorage(i);
973
			tbl.rows[i].cells[2].children[0].value = ae.getLimitNormalA(i);
974
			tbl.rows[i].cells[3].children[0].value = ae.getLimitShieldA(i);
975
		}
976
	} else {
977
		const lvl = ae.getOwnLevel();
978
		tbl.rows[lvl].cells[1].children[0].value = ae.getLimitStorage(lvl);
979
		tbl.rows[lvl].cells[2].children[0].value = ae.getLimitNormalA(lvl);
980
		tbl.rows[lvl].cells[3].children[0].value = ae.getLimitShieldA(lvl);
981
	}
982
}
983
984
function deleteAddress(addr) {
985
	const buttons = document.querySelectorAll("#tbl_addrs button");
986
	buttons.forEach(function(btn) {btn.disabled = true;});
987
988
	let addressToDelete = -1;
989
	for (let i = 0; i < ae.getAddressCount(); i++) {
990
		if (addr === ae.getAddress(i)) {
991
			addressToDelete = i;
992
			break;
993
		}
994
	}
995
996
	if (addressToDelete === -1) return;
997
998
	ae.Address_Delete(addressToDelete, function(error1) {
999
		if (error1 !== 0) {
1000
			buttons.forEach(function(btn) {btn.disabled = false;});
1001
			errorDialog(error1);
1002
			return;
1003
		}
1004
1005
		document.getElementById("tbl_addrs").deleteRow(addressToDelete);
1006
		document.getElementById("write_from").remove(addressToDelete);
1007
1008
		if (ae.getAddressCountNormal() > 0) {
1009
			const apkList = document.getElementById("getapk_addr");
1010
			for (let i = 0; i < apkList.children.length; i++) {
1011
				if (apkList.children[i].value === addr) {
1012
					apkList.remove(i);
1013
					break;
1014
				}
1015
			}
1016
		} else {
1017
			document.getElementById("getapk_addr").replaceChildren();
1018
		}
1019
1020
		updateAddressCounts();
1021
1022
		ae.Private_Update(function(error2) {
1023
			buttons.forEach(function(btn) {btn.disabled = false;});
1024
			if (error2) errorDialog(error2);
1025
		});
1026
	});
1027
}
1028
1029
function setTab(isHistory, tabNum, pageNum) {
1030
	tab = tabNum;
1031
	if (pageNum !== -1) tabs[tab].cur = pageNum;
1032
1033
	document.querySelectorAll("#main1 > nav:first-of-type > button").forEach(function(btn, i) {
1034
		document.querySelectorAll("#main1 > .mid > div")[i].hidden = (tab !== i);
1035
		btn.disabled = (tab === i);
1036
	});
1037
1038
	const bigScreen = window.matchMedia("(min-width: 80em)").matches;
1039
	document.getElementById("main2").hidden = !bigScreen;
1040
	document.getElementById("btn_leave").disabled = bigScreen;
1041
1042
	switch (tab) {
1043
		case TAB_INBOX: showInbox(); break;
1044
		case TAB_DRBOX: showDrbox(); break;
1045
1046
		case TAB_WRITE:
1047
			if (tabs[tab].cur === 0) {
1048
				document.getElementById("div_write_1").hidden = false;
1049
				document.getElementById("div_write_2").hidden = true;
1050
				document.getElementById("write_recv").focus();
1051
			} else if (!writeVerify()) {
1052
				tabs[TAB_WRITE].cur = 0;
1053
				return;
1054
			}
1055
		break;
1056
1057
		case TAB_NOTES:
1058
			if (vaultPage === -2) {
1059
				vaultPage = -1;
1060
1061
				vault.downloadIndex(function(err) {
1062
					if (err === 0) {
1063
						vaultPage = 0;
1064
					}
1065
				});
1066
			}
1067
1068
			switch (tabs[tab].cur) {
1069
				case 0:
1070
					document.getElementById("div_notes").children[0].hidden = false;
1071
					document.getElementById("div_notes").children[1].hidden = true;
1072
					document.getElementById("div_notes").children[2].hidden = true;
1073
				break;
1074
1075
				case 1:
1076
					document.getElementById("div_notes").children[0].hidden = true;
1077
					document.getElementById("div_notes").children[1].hidden = false;
1078
					document.getElementById("div_notes").children[2].hidden = true;
1079
1080
					document.querySelector("#div_notepad meter").value = ae.getPrivateExtraSpace() / ae.getPrivateExtraSpaceMax();
1081
				break;
1082
1083
				case 2:
1084
					document.getElementById("div_notes").children[0].hidden = true;
1085
					document.getElementById("div_notes").children[1].hidden = true;
1086
					document.getElementById("div_notes").children[2].hidden = false;
0 ignored issues
show
introduced by
This node falls through to the next case due to this statement. Please add a comment either directly below this line or between the cases to explain.
Loading history...
1087
1088
				default:
1089
					showFiles();
1090
			}
1091
		break;
1092
1093
		case TAB_TOOLS:
1094
			for (let i = 0; i <= tabs[tab].max; i++) {
1095
				document.getElementById("div_tools").children[i].hidden = (i !== tabs[tab].cur);
1096
			}
1097
		break;
1098
	}
1099
1100
	document.getElementById("btn_dele").disabled = !tabs[tab].btnDele;
1101
	document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
1102
	document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
1103
	document.getElementById("btn_updt").disabled = !tabs[tab].btnUpdt;
1104
1105
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
1106
}
1107
1108
window.onresize = function() {
1109
	setTab(true, tab, tabs[tab].cur);
1110
}
1111
1112
function clearWrite() {
1113
	setTab(false, TAB_WRITE, 0);
1114
1115
	document.querySelector("#write2_pkey > input").value = "";
1116
	document.getElementById("write_body").value = "";
1117
	document.getElementById("write_subj").value = "";
1118
	document.getElementById("write_subj").readOnly = false;
1119
	document.getElementById("write_subj").setAttribute("data-replyid", "");
1120
	document.getElementById("write_recv").value = "";
1121
	document.getElementById("write_recv").readOnly = false;
1122
	document.getElementById("write_recv").focus();
1123
}
1124
1125
function refreshContactList() {
1126
	let opts = [];
1127
1128
	for (let i = 0; i < ae.getContactCount(); i++) {
1129
		const el = document.createElement("option");
1130
		el.value = ae.getContactMail(i);
1131
		opts.push(el);
1132
	}
1133
1134
	if (ae.isUserAdmin()) {
1135
		const el = document.createElement("option");
1136
		el.value = "public";
1137
		opts.push(el);
1138
	}
1139
1140
	document.getElementById("contact_emails").replaceChildren(...opts);
1141
}
1142
1143
function addContact(mail, name, note) {
1144
	const tbl = document.getElementById("tbl_ctact");
1145
	const row = tbl.insertRow(-1);
1146
1147
	let cell = row.insertCell(-1);
1148
	cell.autocapitalize = "off";
1149
	cell.contentEditable = true;
1150
	cell.inputMode = "email";
1151
	cell.spellcheck = false;
1152
	cell.textContent = mail;
1153
1154
	cell = row.insertCell(-1);
1155
	cell.autocapitalize = "words";
1156
	cell.contentEditable = true;
1157
	cell.spellcheck = false;
1158
	cell.textContent = name;
1159
1160
	cell = row.insertCell(-1);
1161
	cell.autocapitalize = "off";
1162
	cell.contentEditable = true;
1163
	cell.spellcheck = false;
1164
	cell.textContent = note;
1165
1166
	cell = row.insertCell(-1);
1167
	const el = document.createElement("button");
1168
	el.type = "button";
1169
	el.textContent = "X";
1170
	el.onclick = function() {row.remove();};
1171
	cell.appendChild(el);
1172
}
1173
1174
function addContacts() {
1175
	for (let i = 0; i < ae.getContactCount(); i++) {
1176
		addContact(
1177
			ae.getContactMail(i),
1178
			ae.getContactName(i),
1179
			ae.getContactNote(i)
1180
		);
1181
	}
1182
1183
	refreshContactList();
1184
}
1185
1186
function addAddress(num) {
1187
	const addrTable = document.getElementById("tbl_addrs");
1188
	const row = addrTable.insertRow(-1);
1189
	const addr = ae.getAddress(num);
1190
1191
	let cell = row.insertCell(-1);
1192
	let el = document.createElement("input");
1193
	el.type = "text";
1194
	el.size = ae.isAddressShield(num) ? 16 : 15;
1195
1196
	if (document.getElementById("chk_addr_nick").checked) {
1197
		el.minLength = ae.getAddress(num).length;
1198
		el.maxLength = 31;
1199
		el.placeholder = ae.getAddress(num);
1200
		el.value = ae.getAddressNick(num);
1201
1202
		el.onchange = function() {
1203
			ae.setAddressNick(num, this.value);
1204
		};
1205
	} else {
1206
		el.value = addr;
1207
		el.readOnly = true;
1208
1209
		el.onclick = function() {
1210
			navigator.clipboard.writeText((ae.isAddressShield(num)? ae.shieldMix(el.value, 0) : el.value) + "@" + ae.getDomainEml());
1211
		};
1212
	}
1213
1214
	cell.appendChild(el);
1215
1216
	cell = row.insertCell(-1);
1217
	el = document.createElement("input");
1218
	el.type = "checkbox";
1219
	el.checked = ae.getAddressAccInt(num);
1220
	cell.appendChild(el);
1221
1222
	cell = row.insertCell(-1);
1223
	el = document.createElement("input");
1224
	el.type = "checkbox";
1225
	el.checked = ae.getAddressAccExt(num);
1226
	cell.appendChild(el);
1227
1228
	cell = row.insertCell(-1);
1229
	el = document.createElement("input");
1230
	el.type = "checkbox";
1231
	el.checked = ae.getAddressAllVer(num);
1232
	cell.appendChild(el);
1233
1234
	cell = row.insertCell(-1);
1235
	el = document.createElement("input");
1236
	el.type = "checkbox";
1237
	el.checked = ae.getAddressAttach(num);
1238
	cell.appendChild(el);
1239
1240
	cell = row.insertCell(-1);
1241
	el = document.createElement("input");
1242
	el.type = "checkbox";
1243
	el.checked = ae.getAddressSecure(num);
1244
	cell.appendChild(el);
1245
1246
	cell = row.insertCell(-1);
1247
	el = document.createElement("input");
1248
	el.type = "checkbox";
1249
	el.checked = ae.getAddressOrigin(num);
1250
	cell.appendChild(el);
1251
1252
	cell = row.insertCell(-1);
1253
	el = document.createElement("button");
1254
	el.type = "button";
1255
	el.textContent = "X";
1256
	el.onclick = function() {deleteAddress(addr);};
1257
	cell.appendChild(el);
1258
1259
	el = document.createElement("option");
1260
	let pref = "";
1261
	let counter = 0;
1262
	for (let i = 0; i < ae.getAddressNick(num).length; i++) {
1263
		if (
1264
		    addr[counter] === ae.getAddressNick(num)[i].toLowerCase()
1265
		|| (addr[counter] === '0' && ae.getAddressNick(num)[i].toLowerCase() == 'o')
1266
		|| (addr[counter] === '1' && (ae.getAddressNick(num)[i].toLowerCase() == 'i' || ae.getAddressNick(num)[i].toLowerCase() == 'l'))
1267
		|| (addr[counter] === 'w' && ae.getAddressNick(num)[i].toLowerCase() == 'v')
1268
		) {
1269
			pref += ae.getAddressNick(num)[i].toLowerCase();
1270
			counter++;
1271
		}
1272
	}
1273
	pref += addr.slice(counter);
1274
1275
	el.value = pref;
1276
	el.textContent = pref + "@" + ae.getDomainEml();
1277
	document.getElementById("write_from").appendChild(el);
1278
1279
	if (addr.length !== 16) {
1280
		el = document.createElement("option");
1281
		el.value = addr;
1282
		el.textContent = addr;
1283
		document.getElementById("getapk_addr").appendChild(el);
1284
	}
1285
}
1286
1287
function addAddresses() {
1288
	document.getElementById("tbl_addrs").replaceChildren();
1289
	document.getElementById("getapk_addr").replaceChildren();
1290
	document.getElementById("write_from").replaceChildren();
1291
1292
	for (let i = 0; i < ae.getAddressCount(); i++) {
1293
		addAddress(i);
1294
	}
1295
}
1296
1297
function addressCreate(addr) {
1298
	document.getElementById("btn_address_create_normal").disabled = true;
1299
	document.getElementById("btn_address_create_shield").disabled = true;
1300
1301
	ae.Address_Create(addr, function(error1) {
1302
		if (error1 !== 0) {
1303
			updateAddressButtons();
1304
			errorDialog(error1, (addr !== "SHIELD") ? document.getElementById("txt_address_create_normal") : null);
1305
			return;
1306
		}
1307
1308
		ae.Private_Update(function(error2) {
1309
			updateAddressCounts();
1310
1311
			addAddress(ae.getAddressCount() - 1);
1312
			if (addr !== "SHIELD") {
1313
				document.getElementById("txt_address_create_normal").value = "";
1314
				document.getElementById("txt_address_create_normal").focus();
1315
			}
1316
1317
			if (error2 !== 0) errorDialog(error2, (addr !== "SHIELD") ? document.getElementById("txt_address_create_normal") : null);
1318
		});
1319
	});
1320
}
1321
1322
function reloadAccount() {
1323
	updateLimits();
1324
	addOwnAccount();
1325
	addContacts();
1326
	addAddresses();
1327
	updateAddressCounts();
1328
1329
	document.getElementById("fs_admin").disabled = !ae.isUserAdmin();
1330
	document.getElementById("txt_notepad").value = ae.getPrivateExtra();
1331
}
1332
1333
function writeVerify() {
1334
	if (
1335
	   !document.getElementById("write_recv").reportValidity()
1336
	|| !document.getElementById("write_subj").reportValidity()
1337
	|| !document.getElementById("write_body").reportValidity()
1338
	) return false;
1339
1340
	document.getElementById("div_write_1").hidden = true;
1341
	document.getElementById("div_write_2").hidden = false;
1342
1343
	document.getElementById("write2_recv").textContent = document.getElementById("write_recv").value;
1344
	document.getElementById("write2_subj").textContent = document.getElementById("write_subj").value;
1345
	document.getElementById("write2_rply").textContent = document.getElementById("write_subj").getAttribute("data-replyid");
1346
	document.getElementById("write2_body").textContent = document.getElementById("write_body").value;
1347
1348
	if (document.getElementById("write_recv").value.indexOf("@") >= 0) {
1349
		document.getElementById("write2_from").textContent = document.getElementById("write_from").value + "@" + ae.getDomainEml();
1350
		document.getElementById("write2_pkey").hidden = true;
1351
	} else {
1352
		document.getElementById("write2_from").textContent = document.getElementById("write_from").value;
1353
		document.getElementById("write2_pkey").hidden = (document.getElementById("write_recv").value === "public");
1354
	}
1355
1356
	document.querySelector("#write2_send > button").disabled = false;
1357
	document.getElementById("write2_btntxt").textContent = (document.getElementById("write_recv").value === "public") ? "Make" : "Send to";
1358
	return true;
1359
}
1360
1361
// Interface elements
1362
if (window.matchMedia("(prefers-color-scheme: light)").matches) document.querySelector("head > meta[name='theme-color']").content = "#eef";
1363
window.matchMedia("(prefers-color-scheme: light)").onchange = function() {document.querySelector("head > meta[name='theme-color']").content = window.matchMedia("(prefers-color-scheme: light)").matches? "#eef" : "#001";};
1364
1365
window.onpopstate = function(event) {
1366
	if (!isReady || !event.state) return;
1367
	setTab(true, event.state.tab, event.state.page);
1368
	msgDisplay = event.state.msg;
1369
1370
	if (msgDisplay) {
1371
		switch (msgDisplay.type) {
1372
			case "ext": displayMsg(true, false, msgDisplay.num); break;
1373
			case "int": displayMsg(true, true, msgDisplay.num); break;
1374
			case "out": displayOutMsg(true, msgDisplay.num); break;
1375
			case "upl": displayFile(true, msgDisplay.num, null); break;
1376
			case "ext_exp": displayExport(true, false, msgDisplay.num); break;
1377
			case "int_exp": displayExport(true, true, msgDisplay.num); break;
1378
		}
1379
	}
1380
};
1381
1382
document.querySelectorAll("#main1 > nav:first-of-type > button").forEach(function(btn, i) {
1383
	btn.onclick = function() {setTab(false, i, -1);};
1384
});
1385
1386
document.getElementById("btn_left").onclick = function() {
1387
	setTab(false, tab, tabs[tab].cur - 1);
1388
};
1389
1390
document.getElementById("btn_rght").onclick = function() {
1391
	setTab(false, tab, tabs[tab].cur + 1);
1392
};
1393
1394
document.getElementById("btn_dele").onclick = function() {
1395
	this.blur();
1396
1397
	if (tab === TAB_WRITE) clearWrite();
1398
};
1399
1400
document.getElementById("btn_updt").onclick = function() {
1401
	const btn = this;
1402
	btn.disabled = true;
1403
	btn.blur();
1404
1405
	if (tab === TAB_INBOX) {
1406
		document.getElementById("tbl_inbox").style.opacity = 0.5;
1407
1408
		ae.Message_Browse(true, false, function(error) {
1409
			btn.disabled = false;
1410
			document.getElementById("tbl_inbox").style.opacity = 1;
1411
1412
			if (error === 0) {
1413
				showInbox();
1414
			} else {
1415
				errorDialog(error);
1416
			}
1417
		});
1418
	}
1419
};
1420
1421
document.getElementById("btn_mdele").onclick = function() {
1422
	const delId = document.querySelector("article").getAttribute("data-msgid");
1423
	if (!delId) return;
1424
1425
	const btn = this;
1426
	btn.blur();
1427
	btn.disabled = true;
1428
1429
	ae.Message_Delete(delId, function(error) {
1430
		if (error !== 0) {
1431
			btn.disabled = false;
1432
			errorDialog(error);
1433
			return;
1434
		}
1435
1436
		switch (tab) {
1437
			case TAB_INBOX: showInbox(); break;
1438
			case TAB_DRBOX: showDrbox(); break;
1439
			case TAB_NOTES: showFiles(); break;
1440
		}
1441
	});
1442
};
1443
1444
document.getElementById("btn_leave").onclick = function() {
1445
	document.getElementById("main2").hidden = true;
1446
	document.getElementById("main1").hidden = false;
1447
};
1448
1449
document.getElementById("btn_newcontact").onclick = function() {
1450
	addContact("", "", "");
1451
};
1452
1453
document.getElementById("btn_savecontacts").onclick = function() {
1454
	while (ae.getContactCount() > 0) {
1455
		ae.deleteContact(0);
1456
	}
1457
1458
	for (const row of document.getElementById("tbl_ctact").rows) {
1459
		ae.addContact(row.cells[0].textContent, row.cells[1].textContent, row.cells[2].textContent);
1460
	}
1461
1462
	refreshContactList();
1463
1464
	const btn = this;
1465
	btn.disabled = true;
1466
1467
	ae.Private_Update(function(error) {
1468
		btn.disabled = false;
1469
		if (error) errorDialog(error);
1470
	});
1471
};
1472
1473
document.getElementById("chk_addr_nick").onclick = function() {
1474
	addAddresses();
1475
};
1476
1477
document.getElementById("btn_address_create_normal").onclick = function() {
1478
	if (ae.getAddressCountNormal() >= ae.getLimitNormalA(ae.getOwnLevel()) || ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31) return;
1479
1480
	const txtNewAddr = document.getElementById("txt_address_create_normal");
1481
	if (!txtNewAddr.reportValidity()) return;
1482
1483
	addressCreate(txtNewAddr.value.toLowerCase());
1484
};
1485
1486
document.getElementById("txt_address_create_normal").onkeyup = function(event) {
1487
	if (event.key !== "Enter") return;
1488
	event.preventDefault();
1489
	document.getElementById("btn_address_create_normal").click();
1490
};
1491
1492
document.getElementById("btn_address_create_shield").onclick = function() {
1493
	if (ae.getAddressCountShield() >= ae.getLimitShieldA(ae.getOwnLevel()) || ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31) return;
1494
1495
	addressCreate("SHIELD");
1496
};
1497
1498
document.getElementById("btn_address_update").onclick = function() {
1499
	const btn = this;
1500
	btn.disabled = true;
1501
1502
	const rows = document.getElementById("tbl_addrs").rows;
1503
1504
	for (let i = 0; i < rows.length; i++) {
1505
		ae.setAddressAccInt(i, rows[i].getElementsByTagName("input")[1].checked);
1506
		ae.setAddressAccExt(i, rows[i].getElementsByTagName("input")[2].checked);
1507
		ae.setAddressAllVer(i, rows[i].getElementsByTagName("input")[3].checked);
1508
		ae.setAddressAttach(i, rows[i].getElementsByTagName("input")[4].checked);
1509
		ae.setAddressSecure(i, rows[i].getElementsByTagName("input")[5].checked);
1510
		ae.setAddressOrigin(i, rows[i].getElementsByTagName("input")[6].checked);
1511
	}
1512
1513
	ae.Address_Update(function(error) {
1514
		btn.disabled = false;
1515
		if (error) errorDialog(error);
1516
	});
1517
};
1518
1519
1520
document.getElementById("txt_sender").onkeyup = function(event) {
1521
	if (event.key !== "Enter") return;
1522
	event.preventDefault();
1523
	document.getElementById("btn_sender").click();
1524
};
1525
1526
document.getElementById("btn_reg").onclick = function() {
1527
	const btn = document.getElementById("btn_reg");
1528
	const uak = document.getElementById("txt_reg_uak");
1529
	const epk = document.getElementById("txt_reg_epk");
1530
1531
	if (!uak.reportValidity() || !epk.reportValidity()) return;
1532
	btn.disabled = true;
1533
	uak.disabled = true;
1534
	epk.disabled = true;
1535
1536
	ae.Account_Create(uak.value, epk.value, function(error) {
1537
		if (error === 0) {
1538
			addAccountToTable(ae.admin_getUserCount() - 1);
1539
			uak.value = "";
1540
			epk.value = "";
1541
		} else errorDialog(error);
1542
1543
		btn.disabled = false;
1544
		uak.disabled = false;
1545
		epk.disabled = false;
1546
	});
1547
};
1548
1549
document.getElementById("chk_dng_usr").onclick = function() {
1550
	document.getElementById("btn_lowme").disabled = !this.checked || (ae.getOwnLevel() === 0);
1551
	document.getElementById("btn_erame").disabled = !this.checked;
1552
	document.getElementById("btn_delme").disabled = !this.checked;
1553
};
1554
1555
document.getElementById("btn_erame").onclick = function() {
1556
	ae.Message_Delete("ALL", function(error) {
1557
		if (error === 0) {
1558
			document.getElementById("chk_dng_usr").checked = false;
1559
			document.getElementById("chk_dng_usr").onclick();
1560
		} else errorDialog(error);
1561
	});
1562
};
1563
1564
document.getElementById("btn_notepad_restore").onclick = function() {
1565
	document.getElementById("txt_notepad").value = ae.getPrivateExtra();
1566
	document.getElementById("btn_notepad_savepad").disabled = true;
1567
	document.getElementById("txt_notepad").oninput = function() {
1568
		this.oninput = null;
1569
		document.getElementById("btn_notepad_savepad").disabled = false;
1570
		document.getElementById("btn_notepad_savepad").textContent = "Save";
1571
	};
1572
};
1573
1574
document.getElementById("txt_notepad").oninput = function() {
1575
	document.getElementById("btn_notepad_savepad").disabled = false;
1576
};
1577
1578
document.getElementById("btn_notepad_savepad").onclick = function() {
1579
	const btn = this;
1580
	btn.disabled = true;
1581
1582
	const error = ae.setPrivateExtra(document.getElementById("txt_notepad").value);
1583
	if (error !== 0) {
1584
		btn.disabled = false;
1585
		errorDialog(error);
1586
		return;
1587
	}
1588
1589
	ae.Private_Update(function(error2) {
1590
		if (error2 !== 0) {
1591
			btn.disabled = false;
1592
			errorDialog(error2);
1593
		} else {
1594
			document.querySelector("#div_notepad meter").value = ae.getPrivateExtraSpace() / ae.getPrivateExtraSpaceMax();
1595
			btn.textContent = "Saved";
1596
			document.getElementById("txt_notepad").oninput = function() {
1597
				this.oninput = null;
1598
				btn.textContent = "Save";
1599
				btn.disabled = false;
1600
			};
1601
		}
1602
	});
1603
};
1604
1605
document.getElementById("btn_notepad_saveupl").onclick = function() {
1606
	const np = document.getElementById("txt_notepad");
1607
	np.disabled = true;
1608
1609
	let fname = prompt("Save as...", "Untitled");
0 ignored issues
show
Debugging Code Best Practice introduced by
The prompt UI element is often considered obtrusive and is generally only used as a temporary measure. Consider replacing it with another UI element.
Loading history...
1610
	if (!fname.endsWith(".txt")) fname += ".txt";
1611
1612
	ae.Message_Upload(fname, np.value, function(error) {
1613
		if (error === 0) {
1614
			np.value = "";
1615
			showFiles();
1616
			document.getElementById("tbd_accs").children[0].children[1].textContent = Math.round(ae.getTotalMsgBytes() / 1024 / 1024);
1617
		} else errorDialog(error);
1618
1619
		np.disabled = false;
1620
	});
1621
};
1622
1623
document.getElementById("btn_upload").onclick = function() {
1624
	const btn = this;
1625
	const fileSelector = document.createElement("input");
1626
	fileSelector.type = "file";
1627
	fileSelector.click();
1628
1629
	fileSelector.onchange = function() {
1630
		btn.disabled = true;
1631
1632
		const reader = new FileReader();
1633
		reader.onload = function() {
1634
			ae.Message_Upload(fileSelector.files[0].name, new Uint8Array(reader.result), function(error) {
1635
				if (error === 0) {
1636
					showFiles();
1637
					document.getElementById("tbd_accs").children[0].children[1].textContent = Math.round(ae.getTotalMsgBytes() / 1024 / 1024);
1638
				} else errorDialog(error);
1639
1640
				btn.disabled = false;
1641
			});
1642
		};
1643
1644
		reader.readAsArrayBuffer(fileSelector.files[0]);
1645
	};
1646
};
1647
1648
document.getElementById("btn_pg").onclick = function() {
1649
//	localStorage.greeting = document.getElementById("txt_pg").value;
1650
};
1651
1652
document.querySelector("#write2_send > button").onclick = function() {
1653
	const btn = this;
1654
	btn.disabled = true;
1655
1656
	// Public announcement
1657
	if (document.getElementById("write2_recv").textContent === "public") {
1658
		ae.Message_Public(document.getElementById("write_subj").value, document.getElementById("write_body").value, function(error) {
1659
			if (error !== 0) {
1660
				document.getElementById("write2_btntxt").textContent = "Retry making";
1661
				btn.disabled = false;
1662
				errorDialog(error);
1663
				return;
1664
			}
1665
1666
			clearWrite();
1667
			displayMsg(false, true, 0);
1668
		});
1669
1670
		return;
1671
	}
1672
1673
	// Email or internal message
1674
	let apk = null;
1675
	if (document.getElementById("write2_recv").textContent.indexOf("@") === -1) {
1676
		const elApk = document.querySelector("#write2_pkey > input");
1677
		if (!elApk.reportValidity()) {
1678
			btn.disabled = false;
1679
			return;
1680
		}
1681
1682
		try {apk = sodium.from_base64(elApk.value, sodium.base64_variants.ORIGINAL_NO_PADDING);}
1683
		catch(e) {
1684
			errorDialog(1); // Invalid input
1685
			btn.disabled = false;
1686
			return;
1687
		}
1688
	}
1689
1690
	document.getElementById("write2_btntxt").textContent = "Sending to";
1691
1692
	ae.Message_Create(
1693
		document.getElementById("write_subj").value,
1694
		document.getElementById("write_body").value,
1695
		document.getElementById("write_from").value,
1696
		document.getElementById("write_recv").value,
1697
		document.getElementById("write_subj").getAttribute("data-replyid"),
1698
		apk,
1699
		function(error) {
1700
			if (error !== 0) {
1701
				errorDialog(error);
1702
				document.getElementById("write2_btntxt").textContent = "Retry sending to";
1703
				btn.disabled = false;
1704
				return;
1705
			}
1706
1707
			showDrbox();
1708
			clearWrite();
1709
			displayOutMsg(false, 0);
1710
		}
1711
	);
1712
};
1713
1714
document.getElementById("btn_sender").onclick = function() {
1715
	ae.Message_Sender(document.getElementById("txt_sender_hash").value, Date.parse(document.getElementById("txt_sender_date").value) / 1000, function(error, result) {
1716
		if (error !== 0) {
1717
			errorDialog(error);
1718
			return;
1719
		}
1720
1721
		document.getElementById("txt_sender_res").value = result;
1722
	});
1723
};
1724
1725
document.getElementById("btn_limits").onclick = function() {
1726
	const btn = this;
1727
	btn.disabled = true;
1728
1729
	const mib = [parseInt(document.getElementById("lim_mib0").value, 10), parseInt(document.getElementById("lim_mib1").value, 10), parseInt(document.getElementById("lim_mib2").value, 10), parseInt(document.getElementById("lim_mib3").value, 10)];
1730
	const nrm = [parseInt(document.getElementById("lim_nrm0").value, 10), parseInt(document.getElementById("lim_nrm1").value, 10), parseInt(document.getElementById("lim_nrm2").value, 10), parseInt(document.getElementById("lim_nrm3").value, 10)];
1731
	const shd = [parseInt(document.getElementById("lim_shd0").value, 10), parseInt(document.getElementById("lim_shd1").value, 10), parseInt(document.getElementById("lim_shd2").value, 10), parseInt(document.getElementById("lim_shd3").value, 10)];
1732
1733
	ae.Setting_Limits(mib, nrm, shd, function(error) {
1734
		btn.disabled = false;
1735
1736
		if (error !== 0) {
1737
			errorDialog(error);
1738
		} else {
1739
			updateAddressCounts();
1740
		}
1741
	});
1742
};
1743
1744
document.getElementById("getapk_addr").onchange = function() {
1745
	document.getElementById("getapk_result").textContent = ae.getOwnApk(document.getElementById("getapk_addr").value);
1746
};
1747
1748
document.getElementById("txt_umk").onfocus = function() {
1749
//	document.getElementById("greeting").textContent = localStorage.greeting;
1750
};
1751
1752
document.getElementById("txt_umk").onkeyup = function(event) {
1753
	if (event.key !== "Enter") return;
1754
	event.preventDefault();
1755
	document.getElementById("btn_enter").click();
1756
};
1757
1758
document.getElementById("btn_enter").onclick = function() {
1759
	const txtUmk = document.getElementById("txt_umk");
1760
1761
	if (txtUmk.value === "") {
1762
		ae.reset();
1763
		document.getElementById("greeting").textContent = "Data cleared";
1764
		return;
1765
	}
1766
1767
	if (!txtUmk.reportValidity()) return;
1768
1769
	const btn = this;
1770
	btn.disabled = true;
1771
1772
	document.getElementById("txt_umk").disabled = true;
1773
1774
	ae.setKeys(txtUmk.value, function(successSetKeys) {
1775
		if (!successSetKeys) {
1776
			document.getElementById("txt_umk").disabled = false;
1777
			txtUmk.focus();
1778
1779
			document.getElementById("greeting").textContent = "SetKeys failed";
1780
			btn.disabled = false;
1781
			return;
1782
		}
1783
1784
		document.body.style.cursor = "wait";
1785
		document.getElementById("greeting").textContent = "Connecting...";
1786
1787
		if (vaultPage === -3) {
1788
			vault.setKeys(txtUmk.value, function(vaultKeysOk) {
1789
				if (vaultKeysOk) vaultPage = -2;
1790
			});
1791
		}
1792
1793
		ae.Message_Browse(true, true, function(errorBrowse) {
1794
			document.body.style.cursor = "";
1795
1796
			if (errorBrowse !== 0 && errorBrowse !== 0x09) {
1797
				let errorMsg = ae.getErrorMessage(errorBrowse);
1798
				if (typeof(errorMsg) == "object") errorMsg = errorMsg[1];
1799
1800
				document.getElementById("greeting").textContent = errorMsg + " ("+ ((errorBrowse >= 400) ? errorBrowse : "0x" + errorBrowse.toString(16).padStart(2, "0").toUpperCase()) + ")";
1801
				document.getElementById("txt_umk").disabled = false;
1802
				btn.disabled = false;
1803
				btn.focus();
1804
				return;
1805
			}
1806
1807
			txtUmk.value = "";
1808
			document.getElementById("div_begin").hidden = true;
1809
			document.getElementById("div_main").hidden = false;
1810
			isReady = true;
1811
			reloadAccount();
1812
			history.replaceState({tab: 0, page: 0, msg: msgDisplay}, null);
1813
			setTab(true, 0, 0);
1814
1815
			if (errorBrowse !== 0) errorDialog(errorBrowse);
1816
			if (!ae.isUserAdmin()) return;
1817
1818
			ae.Account_Browse(function(errorAcc) {
1819
				if (errorAcc === 0) {
1820
					for (let i = 0; i < ae.admin_getUserCount(); i++) {addAccountToTable(i);}
1821
					updateLimits();
1822
				} else {
1823
					errorDialog(errorAcc);
1824
				}
1825
			});
1826
		});
1827
	});
1828
};
1829
1830
});
1831